/****************************************************************************
**
****************************************************************************/

#include <QReadWriteLock>
#include <QFile>

#include "util.h"
#include "controllerMain.h"
#include "baseConfigure.h"
#include "baseUpdate.h"

#include "../../controller/controller_can.h"
#include "../../controller/controller_fifo.h"
#include "../../controller/controller_protocol.h"

#include <QDebug>
#define CONTROLLERMAIN_DEBUG

/*------------------------------------------------------------------------------------------------------------------------------------------------*/

extern struct __fifo controller_fifo;

/*------------------------------------------------------------------------------------------------------------------------------------------------*/

static QReadWriteLock StopChargeServiceLock;

/*------------------------------------------------------------------------------------------------------------------------------------------------*/

//cmd flag
QList<bool> ControllerParserMain::stop_charging_service_ = {false, false};

/**********************************************************************帧信息***********************************************************************/

con_frame_info_t ControllerParserMain::con_frame_info[0xFF];

/**********************************************************************命令帧***********************************************************************/

/* 充电启动帧应答 */
con_feedback_start_charg_t ControllerParserMain::con_feedback_start_charg[CON_MAX_PORT_NUM];

/* 充电停止帧应答 */
con_feedback_stop_charg_t ControllerParserMain::con_feedback_stop_charg[CON_MAX_PORT_NUM];

/* 强制启动帧应答 */
con_feedback_startup_force_t ControllerParserMain::con_feedback_startup_force[CON_MAX_PORT_NUM];

/* 对时帧应答 */
con_feedback_time_sync_t ControllerParserMain::con_feedback_time_sync[CON_MAX_PORT_NUM];

/* 版本校验帧应答 */
con_feedback_version_check_t ControllerParserMain::con_feedback_version_check[CON_MAX_PORT_NUM];

/* 电子锁控制帧应答 */
con_feedback_lock_ctrl_t ControllerParserMain::con_feedback_lock_ctrl[CON_MAX_PORT_NUM];

/* 功率调节帧应答 */
con_feedback_power_ctrl_t ControllerParserMain::con_feedback_power_ctrl[CON_MAX_PORT_NUM];

/* 系统参数读取帧应答 */
con_feedback_sys_get_t ControllerParserMain::con_feedback_sys_get[CON_MAX_PORT_NUM];

/* 系统参数配置帧应答 */
con_feedback_sys_set_t ControllerParserMain::con_feedback_sys_set[CON_MAX_PORT_NUM];

/* 获取充电前车辆信息帧应答 */
con_feedback_carinfo_t ControllerParserMain::con_feedback_carinfo[CON_MAX_PORT_NUM];

/* 升级启动应答帧 */
con_feedback_start_update_t ControllerParserMain::con_feedback_start_update;

/* 升级数据应答帧 */
con_feedback_update_data_t ControllerParserMain::con_feedback_update_data;

/* 升级结果帧请求 */
con_update_result_t ControllerParserMain::con_update_result;

/* 系统自检应答帧 */
con_feedback_system_check_t ControllerParserMain::con_feedback_system_check;

/**********************************************************************状态帧**********************************************************************/

/* 启动充电结果帧请求 */
con_charg_start_result_t ControllerParserMain::con_charg_start_result[CON_MAX_PORT_NUM];

/* 停止充电结果帧请求 */
con_charg_stop_result_t ControllerParserMain::con_charg_stop_result[CON_MAX_PORT_NUM];

/**********************************************************************数据帧**********************************************************************/

/* 遥测帧请求 */
con_telemetry_t ControllerParserMain::con_telemetry[CON_MAX_PORT_NUM];

/* 遥信帧请求 */
con_telecommand_t ControllerParserMain::con_telecommand[CON_MAX_PORT_NUM];

/**********************************************************************心跳帧**********************************************************************/

/* 心跳帧应答 */
con_feedback_heartbeat_t ControllerParserMain::con_feedback_heartbeat[CON_MAX_PORT_NUM];

/**********************************************************************错误帧**********************************************************************/

/* 充电控制器错误帧请求 */
con_controller_error_t ControllerParserMain::con_controller_error[CON_MAX_PORT_NUM];

/*************************************************************************************************************************************************/

ControllerParserMain::ControllerParserMain(QObject *parent) : QThread(parent),
    m_quit(false)
{
    for (int index = 0; index < CON_MAX_PORT_NUM; index++) {
        con_telecommand[index].connect_bus = 1;
    }
}

ControllerParserMain::~ControllerParserMain()
{
    m_quit = true;
    wait();
}

bool ControllerParserMain::StopChargingService(quint8 gunno)
{
    bool res = false;

    StopChargeServiceLock.lockForRead();
    res = stop_charging_service_.at(gunno);
    StopChargeServiceLock.unlock();

    return res;
}

void ControllerParserMain::SetStopChargingService(quint8 gunno)
{
    StopChargeServiceLock.lockForWrite();
    stop_charging_service_.replace(gunno, true);
    StopChargeServiceLock.unlock();
}

void ControllerParserMain::ClearStopChargingService(quint8 gunno)
{
    StopChargeServiceLock.lockForWrite();
    stop_charging_service_.replace(gunno, false);
    StopChargeServiceLock.unlock();
}

void ControllerParserMain::run()
{
    uint32_t frame_id = 0;
    uint8_t  buffer[CAN_MAX_DLEN] = {0};

    uint8_t cnt = 0, frame_index = 0, gun_no = 0;

    while (!m_quit) {
        if (fifo_is_empty(&controller_fifo)) {
            msleep(m_cycle);
            continue;
        }

        if ((sizeof(uint32_t) + sizeof(uint8_t) * CAN_MAX_DLEN) > fifo_len(&controller_fifo)) {
            msleep(m_cycle);
            continue;
        }

        fifo_out(&controller_fifo, (uint8_t *) & (frame_id), sizeof(frame_id));
        fifo_out(&controller_fifo, (uint8_t *) & (buffer), CAN_MAX_DLEN);

        switch ((frame_id >> 16) & 0xFF) {
        case CON_PDUFORMAT_FEEDBACK_START_CHARG:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_start_charg[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_start_charg_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG].timeout = 2000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG].pduformat = CON_PDUFORMAT_FEEDBACK_START_CHARG;

            //Lock
            ControllerSendMain::con_lock_ctrl[gun_no - CONGUNNOA].gnu_no = gun_no;
            ControllerSendMain::con_lock_ctrl[gun_no - CONGUNNOA].lock_index = 0;
            ControllerSendMain::con_lock_ctrl[gun_no - CONGUNNOA].lock_param = 1;
            ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].gunno = gun_no;
            ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].cycle = 250;
            ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].count = 0;
            ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].timeout = 5000;
            ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].time = controller_time();
            ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].pduformat = CON_PDUFORMAT_LOCK_CTRL;
            break;
        case CON_PDUFORMAT_FEEDBACK_STOP_CHARG:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_stop_charg[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_stop_charg_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_STOP_CHARG].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STOP_CHARG].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STOP_CHARG].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STOP_CHARG].timeout = 2000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STOP_CHARG].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STOP_CHARG].pduformat = CON_PDUFORMAT_FEEDBACK_STOP_CHARG;
            break;
        case CON_PDUFORMAT_FEEDBACK_TIME_SYNC:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_time_sync[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_time_sync_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_TIME_SYNC].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_TIME_SYNC].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_TIME_SYNC].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_TIME_SYNC].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_TIME_SYNC].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_TIME_SYNC].pduformat = CON_PDUFORMAT_FEEDBACK_TIME_SYNC;
            break;
        case CON_PDUFORMAT_FEEDBACK_VERSION_CHECK:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_version_check[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_version_check_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_VERSION_CHECK].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_VERSION_CHECK].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_VERSION_CHECK].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_VERSION_CHECK].timeout = 2000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_VERSION_CHECK].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_VERSION_CHECK].pduformat = CON_PDUFORMAT_FEEDBACK_VERSION_CHECK;
            break;
        case CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_startup_force[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_version_check_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE].timeout = 2000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE].pduformat = CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE;
            break;
        case CON_PDUFORMAT_FEED_BACK_LOCK_CTRL:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_lock_ctrl[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_lock_ctrl_t));

            printf("[CONTROLLER]-> %s [%s, result: %s] \n", (con_feedback_lock_ctrl[gun_no - CONGUNNOA].lock_param > 0) ? "lock" : "unLock",
                   CONGUNNOA == gun_no ? "No.a" : "No.b", (con_feedback_lock_ctrl[gun_no - CONGUNNOA].res_code > 0) ? "success" : "fail");

            con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL].count += 1;
            con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL].timeout = 2000;
            con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL].pduformat = CON_PDUFORMAT_FEED_BACK_LOCK_CTRL;
            break;
        case CON_PDUFORMAT_FEEDBACK_POWER_CTRL:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_power_ctrl[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_power_ctrl_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL].timeout = 2000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL].pduformat = CON_PDUFORMAT_FEEDBACK_POWER_CTRL;
            break;
        case CON_PDUFORMAT_SYS_GET_SET:
            frame_index = buffer[0];
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            switch (frame_index) {
            case 0x01:
                con_feedback_sys_get[CONGUNNOA].gnu_no = buffer[4];
                con_feedback_sys_get[CONGUNNOA].set_type = buffer[5];
                con_feedback_sys_get[CONGUNNOA].lock_type = buffer[6];
                con_feedback_sys_get[CONGUNNOA].temp_type = buffer[7];
                break;
            case 0x02:
                con_feedback_sys_get[CONGUNNOA].meter_baud = buffer[2];
                con_feedback_sys_get[CONGUNNOA].insulation = buffer[3];
                con_feedback_sys_get[CONGUNNOA].bleed = buffer[4];
                con_feedback_sys_get[CONGUNNOA].fan = buffer[5];
                con_feedback_sys_get[CONGUNNOA].travel_switch = buffer[6];
                con_feedback_sys_get[CONGUNNOA].model_type = buffer[7];
                break;
            case 0x03:
                con_feedback_sys_get[CONGUNNOA].lock_fb = buffer[2];
                con_feedback_sys_get[CONGUNNOA].in_feedback = buffer[3];
                con_feedback_sys_get[CONGUNNOA].temp_ctrl = buffer[4];
                con_feedback_sys_get[CONGUNNOA].out_sampling = buffer[5];
                con_feedback_sys_get[CONGUNNOA].meter_kw = buffer[6];
                con_feedback_sys_get[CONGUNNOA].ct = buffer[7];
                break;
            case 0x04:
                con_feedback_sys_get[CONGUNNOA].gnu_type = buffer[2];
                con_feedback_sys_get[CONGUNNOA].model_vol_max = (uint16_t)(buffer[3]) + (uint16_t)(buffer[4] << 8);
                con_feedback_sys_get[CONGUNNOA].model_vol_min = (uint16_t)(buffer[5]) + (uint16_t)(buffer[6] << 8);
                con_feedback_sys_get[CONGUNNOA].model_cur_max = (uint16_t)(buffer[7]);
                break;
            case 0x05:
                con_feedback_sys_get[CONGUNNOA].model_cur_max = con_feedback_sys_get[CONGUNNOA].model_cur_max + (uint16_t)(buffer[2] << 8);
                con_feedback_sys_get[CONGUNNOA].model_cur_min = (uint16_t)(buffer[3]) + (uint16_t)(buffer[4] << 8);
                con_feedback_sys_get[CONGUNNOA].gunno_a_model_num = buffer[5];
                con_feedback_sys_get[CONGUNNOA].gunno_b_model_num = buffer[6];

                con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].gunno = gun_no;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].cycle = 250;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].count += 1;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].timeout = 5000;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].time = 0x00;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].pduformat = CON_PDUFORMAT_FEEDBACK_SYS_GET_SET;
                break;
            default:
                break;
            }
            break;
        case CON_PDUFORMAT_FEEDBACK_SYS_GET_SET:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_sys_set[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_sys_set_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].pduformat = CON_PDUFORMAT_FEEDBACK_SYS_GET_SET;
            break;
        case CON_PDUFORMAT_FEEDBACK_CARINFO:
            frame_index = buffer[0];
            gun_no = buffer[1];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            switch (frame_index) {
            case 0x01:
                con_feedback_carinfo[gun_no - CONGUNNOA].gnu_no = buffer[4];
                memcpy(&con_feedback_carinfo[gun_no - CONGUNNOA].vin[0], &buffer[5], 8 - 4 - 1);
                break;
            case 0x02:
                memcpy(&con_feedback_carinfo[gun_no - CONGUNNOA].vin[3], &buffer[2], 8 - 2);
                break;
            case 0x03:
                memcpy(&con_feedback_carinfo[gun_no - CONGUNNOA].vin[9], &buffer[2], 8 - 2);
                break;
            case 0x04:
                memcpy(&con_feedback_carinfo[gun_no - CONGUNNOA].vin[15], &buffer[2], 2);

                printf("[CONTROLLER]-> vin ");
                for (cnt = 0; cnt < sizeof(con_feedback_carinfo[gun_no - CONGUNNOA].vin); cnt++) {
                    if ((con_feedback_carinfo[gun_no - CONGUNNOA].vin[cnt] >= 0x20) && (con_feedback_carinfo[gun_no - CONGUNNOA].vin[cnt] <= 0x7E)) {
                        printf("[%c] ", con_feedback_carinfo[gun_no - CONGUNNOA].vin[cnt]);
                    } else {
                        printf("<0x%02X> ", con_feedback_carinfo[gun_no - CONGUNNOA].vin[cnt]);
                    }
                }
                printf("\n");

                con_frame_info[CON_PDUFORMAT_FEEDBACK_CARINFO].gunno = gun_no;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_CARINFO].cycle = 250;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_CARINFO].count += 1;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_CARINFO].timeout = 5000;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_CARINFO].time = 0x00;
                con_frame_info[CON_PDUFORMAT_FEEDBACK_CARINFO].pduformat = CON_PDUFORMAT_FEEDBACK_SYS_GET_SET;
                break;
            default:
                break;
            }
            break;
        case CON_PDUFORMAT_FEEDBACK_START_UPDATE:
            memcpy(&con_feedback_start_update, buffer, sizeof(con_feedback_start_update_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE].gunno = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE].pduformat = CON_PDUFORMAT_FEEDBACK_START_UPDATE;

            printf("[CONTROLLER]-> start updae [result: %d] \n", con_feedback_start_update.result);
            break;
        case CON_PDUFORMAT_FEEDBACK_UPDATE_DATA:
            memcpy(&con_feedback_update_data, buffer, sizeof(con_feedback_update_data_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_UPDATE_DATA].gunno = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_UPDATE_DATA].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_UPDATE_DATA].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_UPDATE_DATA].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_UPDATE_DATA].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_UPDATE_DATA].pduformat = CON_PDUFORMAT_FEEDBACK_UPDATE_DATA;
            break;
        case CON_PDUFORMAT_UPDATE_RESULT:
            memcpy(&con_update_result, buffer, sizeof(con_update_result_t));

            con_frame_info[CON_PDUFORMAT_UPDATE_RESULT].gunno = 0x00;
            con_frame_info[CON_PDUFORMAT_UPDATE_RESULT].cycle = 250;
            con_frame_info[CON_PDUFORMAT_UPDATE_RESULT].count += 1;
            con_frame_info[CON_PDUFORMAT_UPDATE_RESULT].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_UPDATE_RESULT].time = 0x00;
            con_frame_info[CON_PDUFORMAT_UPDATE_RESULT].pduformat = CON_PDUFORMAT_UPDATE_RESULT;

            printf("[CONTROLLER]-> updae result [result: %d] \n", con_feedback_start_update.result);
            break;
        case CON_PDUFORMAT_FEEDBACK_SYS_CHECK:
            memcpy(&con_feedback_system_check, buffer, sizeof(con_feedback_system_check_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_CHECK].gunno = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_CHECK].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_CHECK].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_CHECK].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_CHECK].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_CHECK].pduformat = CON_PDUFORMAT_FEEDBACK_SYS_CHECK;
            break;
        case CON_PDUFORMAT_CHARG_START_RESULT:
            frame_index = buffer[0];
            gun_no = buffer[1];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            switch (frame_index) {
            case 0x01:
                con_charg_start_result[gun_no - CONGUNNOA].gnu_no = buffer[4];
                con_charg_start_result[gun_no - CONGUNNOA].ctrl_flag = buffer[5];
                con_charg_start_result[gun_no - CONGUNNOA].start_result = buffer[6];
                con_charg_start_result[gun_no - CONGUNNOA].charg_bms_version[0] = buffer[7];
                break;
            case 0x02:
                con_charg_start_result[gun_no - CONGUNNOA].charg_bms_version[1] = buffer[2];
                con_charg_start_result[gun_no - CONGUNNOA].charg_bms_version[2] = buffer[3];
                con_charg_start_result[gun_no - CONGUNNOA].bms_charg_version[0] = buffer[4];
                con_charg_start_result[gun_no - CONGUNNOA].bms_charg_version[1] = buffer[5];
                con_charg_start_result[gun_no - CONGUNNOA].bms_charg_version[2] = buffer[6];
                con_charg_start_result[gun_no - CONGUNNOA].Charg_bms_hand_res = buffer[7];
                break;
            case 0x03:
                con_charg_start_result[gun_no - CONGUNNOA].battrey_type = buffer[2];
                con_charg_start_result[gun_no - CONGUNNOA].temp_max = buffer[3];
                con_charg_start_result[gun_no - CONGUNNOA].bms_vol_max = (uint16_t)buffer[4] + (uint16_t)(buffer[5] << 8);
                con_charg_start_result[gun_no - CONGUNNOA].vol_max = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
                break;
            case 0x04:
                con_charg_start_result[gun_no - CONGUNNOA].cur_max = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_charg_start_result[gun_no - CONGUNNOA].ot_vol = (uint16_t)buffer[4] + (uint16_t)(buffer[5] << 8);
                con_charg_start_result[gun_no - CONGUNNOA].vol = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
                break;
            case 0x05:
                con_charg_start_result[gun_no - CONGUNNOA].ot_ah = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_charg_start_result[gun_no - CONGUNNOA].ot_kwh = (uint16_t)buffer[4] + (uint16_t)(buffer[5] << 8);
                con_charg_start_result[gun_no - CONGUNNOA].soc = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
                break;
            case 0x06:
                con_charg_start_result[gun_no - CONGUNNOA].out_vol_max = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_charg_start_result[gun_no - CONGUNNOA].out_vol_min = (uint16_t)buffer[4] + (uint16_t)(buffer[5] << 8);
                con_charg_start_result[gun_no - CONGUNNOA].out_cur_max = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
                break;
            case 0x07:
                memcpy(&con_charg_start_result[gun_no - CONGUNNOA].vin[0], &buffer[2], 8 - 2);
                break;
            case 0x08:
                memcpy(&con_charg_start_result[gun_no - CONGUNNOA].vin[6], &buffer[2], 8 - 2);
                break;
            case 0x09:
                memcpy(&con_charg_start_result[gun_no - CONGUNNOA].vin[12], &buffer[2], 5);

                printf("[CONTROLLER]-> start charging [%s, result: %s] \n", CONGUNNOA == gun_no ? "No.a" : "No.b", (con_charg_start_result[gun_no - CONGUNNOA].start_result > 0) ? "fail" : "success");

                con_frame_info[CON_PDUFORMAT_CHARG_START_RESULT].gunno = gun_no;
                con_frame_info[CON_PDUFORMAT_CHARG_START_RESULT].cycle = 250;
                con_frame_info[CON_PDUFORMAT_CHARG_START_RESULT].count += 1;
                con_frame_info[CON_PDUFORMAT_CHARG_START_RESULT].timeout = 5000;
                con_frame_info[CON_PDUFORMAT_CHARG_START_RESULT].time = 0x00;
                con_frame_info[CON_PDUFORMAT_CHARG_START_RESULT].pduformat = CON_PDUFORMAT_CHARG_START_RESULT;

                //feedback
                ControllerSendMain::con_feedback_charg_start_result[gun_no - CONGUNNOA].gnu_no = gun_no;
                ControllerSendMain::con_feedback_charg_start_result[gun_no - CONGUNNOA].ctrl_flag = con_charg_start_result[gun_no - CONGUNNOA].ctrl_flag;
                ControllerSendMain::con_feedback_charg_start_result[gun_no - CONGUNNOA].start_result = 0;
                con_send_data(CON_PDUFORMAT_FEEDBACK_CHARG_START_RESULT, &ControllerSendMain::con_feedback_charg_start_result[gun_no - CONGUNNOA]);
                break;
            default:
                break;
            }
            break;
        case CON_PDUFORMAT_CHARG_STOP_RESULT:
            frame_index = buffer[0];
            gun_no = buffer[1];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            switch (frame_index) {
            case 0x01:
                con_charg_stop_result[gun_no - CONGUNNOA].gnu_no = buffer[4];
                con_charg_stop_result[gun_no - CONGUNNOA].result_code = buffer[5];
                con_charg_stop_result[gun_no - CONGUNNOA].stop_result = buffer[6];
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_reason_code.bms_reason_code = buffer[7];
                break;
            case 0x02:
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_fault_code.bms_fault_code = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_error_code.bms_error_code = buffer[4];
                con_charg_stop_result[gun_no - CONGUNNOA].soc = buffer[5];
                con_charg_stop_result[gun_no - CONGUNNOA].vol_min = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
                break;
            case 0x03:
                con_charg_stop_result[gun_no - CONGUNNOA].vol_max = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_charg_stop_result[gun_no - CONGUNNOA].temp_min = buffer[4];
                con_charg_stop_result[gun_no - CONGUNNOA].temp_max = buffer[5];
                con_charg_stop_result[gun_no - CONGUNNOA].con_spn2560xx_timeout.spn2560xx_timeout = buffer[6];
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_tmra_timeout.bms_tmra_timeout = buffer[7];
                break;
            case 0x04:
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_cscs_timeout.bms_cscs_timeout = buffer[2];
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_csbo_timeout.bms_csbo_timeout = buffer[3];
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_timeout.bms_bms_timeout = buffer[4];
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_bpbrc_timeout.bms_bpbrc_timeout = buffer[5];
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_bsbcbsc_timeout.bms_bsbcbsc_timeout = buffer[6];
                con_charg_stop_result[gun_no - CONGUNNOA].con_bms_bscoe_timeout.bms_bscoe_timeout = buffer[7];
                break;
            case 0x05:
                con_charg_stop_result[gun_no - CONGUNNOA].fault_code_one = buffer[2];
                con_charg_stop_result[gun_no - CONGUNNOA].fault_code_two = buffer[3];

                printf("[CONTROLLER]-> stop charging [%s, result: %s] \n", CONGUNNOA == gun_no ? "No.a" : "No.b", (con_charg_stop_result[gun_no - CONGUNNOA].stop_result > 0) ? "fail" : "success");

                con_frame_info[CON_PDUFORMAT_CHARG_STOP_RESULT].gunno = gun_no;
                con_frame_info[CON_PDUFORMAT_CHARG_STOP_RESULT].cycle = 250;
                con_frame_info[CON_PDUFORMAT_CHARG_STOP_RESULT].count += 1;
                con_frame_info[CON_PDUFORMAT_CHARG_STOP_RESULT].timeout = 5000;
                con_frame_info[CON_PDUFORMAT_CHARG_STOP_RESULT].time = 0x00;
                con_frame_info[CON_PDUFORMAT_CHARG_STOP_RESULT].pduformat = CON_PDUFORMAT_CHARG_STOP_RESULT;

                //feedback
                ControllerSendMain::con_feedback_charg_stop_result[gun_no - CONGUNNOA].gnu_no = gun_no;
                ControllerSendMain::con_feedback_charg_stop_result[gun_no - CONGUNNOA].result_code = con_charg_stop_result[gun_no - CONGUNNOA].result_code;
                ControllerSendMain::con_feedback_charg_stop_result[gun_no - CONGUNNOA].stop_result = 0;
                con_send_data(CON_PDUFORMAT_FEEDBACK_CHARG_STOP_RESULT, &ControllerSendMain::con_feedback_charg_stop_result[gun_no - CONGUNNOA]);

                //Unlock
                ControllerSendMain::con_lock_ctrl[gun_no - CONGUNNOA].gnu_no = gun_no;
                ControllerSendMain::con_lock_ctrl[gun_no - CONGUNNOA].lock_index = 0;
                ControllerSendMain::con_lock_ctrl[gun_no - CONGUNNOA].lock_param = 0;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].gunno = gun_no;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].cycle = 250;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].count = 0;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].timeout = 5000;
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].time = controller_time();
                ControllerSendMain::con_frame_info[CON_PDUFORMAT_LOCK_CTRL].pduformat = CON_PDUFORMAT_LOCK_CTRL;

                ControllerParserMain::SetStopChargingService(gun_no - CONGUNNOA); //stop charging
                break;
            default:
                break;
            }
            break;
        case CON_PDUFORMAT_TELEMETRY:
            frame_index = buffer[0];
            gun_no = buffer[1];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            switch (frame_index) {
            case 0x01:
                con_telemetry[gun_no - CONGUNNOA].gnu_no = buffer[4];
                con_telemetry[gun_no - CONGUNNOA].charg_out_vol = (uint16_t)buffer[5] + (uint16_t)(buffer[6] << 8);
                break;
            case 0x02:
                con_telemetry[gun_no - CONGUNNOA].charg_out_cur = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_telemetry[gun_no - CONGUNNOA].soc = (uint16_t)buffer[4] + (uint16_t)(buffer[5] << 8);
                con_telemetry[gun_no - CONGUNNOA].temp_min = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
                break;
            case 0x03:
                con_telemetry[gun_no - CONGUNNOA].temp_max = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_telemetry[gun_no - CONGUNNOA].vol_max = (uint16_t)buffer[4] + (uint16_t)(buffer[5] << 8);
                con_telemetry[gun_no - CONGUNNOA].vol_min = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
                break;
            case 0x04:
                con_telemetry[gun_no - CONGUNNOA].charg_entemp = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_telemetry[gun_no - CONGUNNOA].charg_guid_vol = (uint16_t)buffer[4] + (uint16_t)(buffer[5] << 8);
                con_telemetry[gun_no - CONGUNNOA].surpl_charg_time = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
                break;
            case 0x05:
                con_telemetry[gun_no - CONGUNNOA].vol = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);
                con_telemetry[gun_no - CONGUNNOA].power =
                    (uint32_t)buffer[4] + (uint32_t)(buffer[5] << 8) + (uint32_t)(buffer[6] << 16) + (uint32_t)(buffer[7] << 24);
                break;
            case 0x06:
                con_telemetry[gun_no - CONGUNNOA].elect =
                    (uint32_t)buffer[2] + (uint32_t)(buffer[3] << 8) + (uint32_t)(buffer[4] << 16) + (uint32_t)(buffer[5] << 24);
                con_telemetry[gun_no - CONGUNNOA].demand_vol = (uint16_t)buffer[6] + (uint16_t)(buffer[7] << 8);
            case 0x07:
                con_telemetry[gun_no - CONGUNNOA].demand_cur = (uint16_t)buffer[2] + (uint16_t)(buffer[3] << 8);

                con_frame_info[CON_PDUFORMAT_TELEMETRY].gunno = gun_no;
                con_frame_info[CON_PDUFORMAT_TELEMETRY].cycle = 250;
                con_frame_info[CON_PDUFORMAT_TELEMETRY].count += 1;
                con_frame_info[CON_PDUFORMAT_TELEMETRY].timeout = 5000;
                con_frame_info[CON_PDUFORMAT_TELEMETRY].time = 0x00;
                con_frame_info[CON_PDUFORMAT_TELEMETRY].pduformat = CON_PDUFORMAT_TELEMETRY;
                break;
            default:
                break;
            }
            break;
        case CON_PDUFORMAT_TELECOMMAND:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_telecommand[gun_no - CONGUNNOA], buffer, sizeof(con_telecommand_t));

            con_frame_info[CON_PDUFORMAT_TELECOMMAND].gunno = gun_no;
            con_frame_info[CON_PDUFORMAT_TELECOMMAND].cycle = 250;
            con_frame_info[CON_PDUFORMAT_TELECOMMAND].count += 1;
            con_frame_info[CON_PDUFORMAT_TELECOMMAND].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_TELECOMMAND].time = 0x00;
            con_frame_info[CON_PDUFORMAT_TELECOMMAND].pduformat = CON_PDUFORMAT_TELECOMMAND;
            break;
        case CON_PDUFORMAT_WLINE_TELECOMMAND:
            break;
        case CON_PDUFORMAT_FEEDBACK_HEARTBEAT:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_feedback_heartbeat[gun_no - CONGUNNOA], buffer, sizeof(con_feedback_heartbeat_t));

            con_frame_info[CON_PDUFORMAT_FEEDBACK_HEARTBEAT].gunno = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_HEARTBEAT].cycle = 250;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_HEARTBEAT].count += 1;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_HEARTBEAT].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_HEARTBEAT].time = 0x00;
            con_frame_info[CON_PDUFORMAT_FEEDBACK_HEARTBEAT].pduformat = CON_PDUFORMAT_FEEDBACK_HEARTBEAT;

            ControllerSendMain::set_heartbeat_count(0); //clear zero
            break;
        case CON_PDUFORMAT_CONTROLLER_ERROR:
            gun_no = buffer[0];
            if ((CONGUNNOA != gun_no) && (CONGUNNOB != gun_no)) {
                break;
            }

            memcpy(&con_controller_error[gun_no - CONGUNNOA], buffer, sizeof(con_controller_error_t));

            con_frame_info[CON_PDUFORMAT_CONTROLLER_ERROR].gunno = 0x00;
            con_frame_info[CON_PDUFORMAT_CONTROLLER_ERROR].cycle = 250;
            con_frame_info[CON_PDUFORMAT_CONTROLLER_ERROR].count += 1;
            con_frame_info[CON_PDUFORMAT_CONTROLLER_ERROR].timeout = 5000;
            con_frame_info[CON_PDUFORMAT_CONTROLLER_ERROR].time = 0x00;
            con_frame_info[CON_PDUFORMAT_CONTROLLER_ERROR].pduformat = CON_PDUFORMAT_CONTROLLER_ERROR;
            break;
        default:
            break;
        }

        msleep(m_cycle);
    }
}

/*------------------------------------------------------------------------------------------------------------------------------------------------*/

bool ControllerRecvMain::reset_ = false;

ControllerRecvMain::ControllerRecvMain(QObject *parent) : QThread(parent),
    m_quit(false),
    m_cycle(10)
{
}

ControllerRecvMain::~ControllerRecvMain()
{
    m_quit = true;
    wait();
}

void ControllerRecvMain::run()
{
    while (!m_quit) {
        con_yield();

        if (5 <= ControllerSendMain::heartbeat_count()) {
            reset_ = true;
            printf("[CONTROLLER]-> reset can-bus \n");
            ControllerSendMain::set_heartbeat_count(0);
            con_linkkit_reset();
            reset_ = false;
        }

        if (10 > m_cycle) {
            m_cycle = 10;
        }
        msleep(m_cycle);
    }
}

/*-----------------------------------------------------------------------------------------------------------------------------------------------*/

int ControllerSendMain::heartbeat_count_ = {0};

/**********************************************************************帧信息**********************************************************************/

con_frame_info_t ControllerSendMain::con_frame_info[0xFF];

/**********************************************************************命令帧**********************************************************************/

/* 充电启动帧请求 */
con_start_charg_t ControllerSendMain::con_start_charg[CON_MAX_PORT_NUM];

/* 充电停止帧请求 */
con_stop_charg_t ControllerSendMain::con_stop_charg[CON_MAX_PORT_NUM];

/* 强制启动帧请求 */
con_startup_force_t ControllerSendMain::con_startup_force[CON_MAX_PORT_NUM];

/* 对时帧请求 */
con_time_sync_t ControllerSendMain::con_time_sync[CON_MAX_PORT_NUM];

/* 版本校验帧请求 */
con_version_check_t ControllerSendMain::con_version_check[CON_MAX_PORT_NUM];

/* 电子锁控制帧请求 */
con_lock_ctrl_t ControllerSendMain::con_lock_ctrl[CON_MAX_PORT_NUM];

/* 功率调节帧请求 */
con_power_ctrl_t ControllerSendMain::con_power_ctrl[CON_MAX_PORT_NUM];

/* 系统参数配置帧请求 */
con_sys_get_set_t ControllerSendMain::con_sys_get_set[CON_MAX_PORT_NUM];

/* 获取充电前车辆信息帧请求 */
con_carinfo_t ControllerSendMain::con_carinfo[CON_MAX_PORT_NUM];

/* 升级启动请求帧 */
con_start_update_t ControllerSendMain::con_start_update;

/* 升级数据请求帧 */
con_update_data_t ControllerSendMain::con_update_data;

/* 系统自检请求帧 */
con_system_check_t ControllerSendMain::con_system_check;

/**********************************************************************状态帧**********************************************************************/

/* 启动充电结果帧应答 */
con_feedback_charg_start_result_t ControllerSendMain::con_feedback_charg_start_result[CON_MAX_PORT_NUM];

/* 停止充电结果帧应答 */
con_feedback_charg_stop_result_t ControllerSendMain::con_feedback_charg_stop_result[CON_MAX_PORT_NUM];

/**********************************************************************心跳帧**********************************************************************/

/* 心跳帧请求 */
con_heartbeat_t ControllerSendMain::con_heartbeat[CON_MAX_PORT_NUM];

/**********************************************************************错误帧**********************************************************************/

/* TCU错误帧请求 */
con_tcu_error_t ControllerSendMain::con_tcu_error[CON_MAX_PORT_NUM];

/*************************************************************************************************************************************************/

ControllerSendMain::ControllerSendMain(QObject *parent) : QThread(parent),
    m_quit(false),
    m_open(false)
{
    for (int index = 0; index < CON_MAX_PORT_NUM; index++) {
        //初始化版本校验
        con_version_check[index].gnu_no = index + 1;
        con_version_check[index].version = 0x010A;

        //初始化功率限制
        con_power_ctrl[index].gnu_no = index + 1;
        con_power_ctrl[index].cmd_type = 1;
        con_power_ctrl[index].ctrl_param = BaseConfigure::power_ctrl(index);

        //初始化心跳
        con_heartbeat[index].gnu_no = index + 1;
    }

    con_frame_info[CON_PDUFORMAT_VERSION_CHECK].cycle = 500;
    con_frame_info[CON_PDUFORMAT_POWER_CTRL].cycle = 250;
}

ControllerSendMain::~ControllerSendMain()
{
    con_linkkit_free();

    m_quit = true;
    wait();
}

quint64 ControllerSendMain::timestamp_ms()
{
    return controller_time();
}

void ControllerSendMain::run()
{
    quint64 time = 0;
    quint16 cycle = 0;

#ifndef __arm__
    return;
#endif

    if (!m_open) {
        if (0 > con_linkkit_new()) {
            m_open = false;
            return;
        }
        m_open = true;
    }

    do {
        con_power_ctrl[kGunNumberA].ctrl_param = BaseConfigure::power_ctrl(kGunNumberA) * 10;
        con_power_ctrl[kGunNumberB].ctrl_param = BaseConfigure::power_ctrl(kGunNumberB) * 10;
        if ((con_power_ctrl[kGunNumberA].ctrl_param > 0) && (con_power_ctrl[kGunNumberB].ctrl_param > 0)) {
            break;
        }
        msleep(m_cycle);
    } while (1);


    time = controller_time();
    while (1) {
        if (CON_PDUFORMAT_FEEDBACK_VERSION_CHECK == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_VERSION_CHECK].pduformat) {
            memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_VERSION_CHECK]), 0x00, sizeof(con_frame_info_t));
            break;
        } else {
            if (controller_time() - time > 30 * 1000) {
                break;
            } else {
                if (++cycle >= con_frame_info[CON_PDUFORMAT_VERSION_CHECK].cycle / m_cycle) {
                    cycle = 0;
                    con_heartbeat[kGunNumberA].sequence_number++;
                    con_send_data(CON_PDUFORMAT_HEARTBEAT, &con_heartbeat[kGunNumberA]);
                    con_send_data(CON_PDUFORMAT_VERSION_CHECK, &con_version_check[kGunNumberA]);
                    con_heartbeat[kGunNumberB].sequence_number++;
                    con_send_data(CON_PDUFORMAT_HEARTBEAT, &con_heartbeat[kGunNumberB]);
                    con_send_data(CON_PDUFORMAT_VERSION_CHECK, &con_version_check[kGunNumberB]);
                }
            }
        }
        msleep(m_cycle);
    }

    time = controller_time();
    while (1) {
        if (CON_PDUFORMAT_FEEDBACK_POWER_CTRL == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL].pduformat) {
            memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL]), 0x00, sizeof(con_frame_info_t));
            break;
        } else {
            if (controller_time() - time > 30 * 1000) {
                break;
            } else {
                if (++cycle >= con_frame_info[CON_PDUFORMAT_POWER_CTRL].cycle / m_cycle) {
                    cycle = 0;
                    con_heartbeat[kGunNumberA].sequence_number++;
                    con_send_data(CON_PDUFORMAT_HEARTBEAT, &con_heartbeat[kGunNumberA]);
                    con_send_data(CON_PDUFORMAT_POWER_CTRL, &con_power_ctrl[kGunNumberA]);
                    con_heartbeat[kGunNumberB].sequence_number++;
                    con_send_data(CON_PDUFORMAT_HEARTBEAT, &con_heartbeat[kGunNumberB]);
                    con_send_data(CON_PDUFORMAT_POWER_CTRL, &con_power_ctrl[kGunNumberB]);
                }
            }
        }
        msleep(m_cycle);
    }

    uint32_t heartbeat = 0;
    bool struct_flag = false;

    while (!m_quit) {
        if (ControllerRecvMain::reset()) {
            msleep(m_cycle);
            continue;
        }

        if (++heartbeat >= 1000 / m_cycle) {
            heartbeat = 0;
            con_heartbeat[kGunNumberA].sequence_number++;
            con_send_data(CON_PDUFORMAT_HEARTBEAT, &con_heartbeat[kGunNumberA]);
            con_heartbeat[kGunNumberB].sequence_number++;
            con_send_data(CON_PDUFORMAT_HEARTBEAT, &con_heartbeat[kGunNumberB]);
            ++heartbeat_count_;
        }

        if (CON_PDUFORMAT_START_CHARG == con_frame_info[CON_PDUFORMAT_START_CHARG].pduformat) {
            if (CON_PDUFORMAT_FEEDBACK_START_CHARG == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG].pduformat) {
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_CHARG]), 0x00, sizeof(con_frame_info_t));
                memset(&(con_frame_info[CON_PDUFORMAT_START_CHARG]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_START_CHARG].time > con_frame_info[CON_PDUFORMAT_START_CHARG].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_START_CHARG]), 0x00, sizeof(con_frame_info_t));
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_START_CHARG].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_START_CHARG, &con_start_charg[con_frame_info[CON_PDUFORMAT_START_CHARG].gunno - CONGUNNOA]);
                        con_frame_info[CON_PDUFORMAT_START_CHARG].count += 1;
                        printf("[CONTROLLER]-> start charging [%s] \n", CONGUNNOA == con_start_charg[con_frame_info[CON_PDUFORMAT_START_CHARG].gunno - CONGUNNOA].gnu_no ? "No.a" : "No.b");
                    }
                }
            }
        }

        if (CON_PDUFORMAT_STOP_CHARG == con_frame_info[CON_PDUFORMAT_STOP_CHARG].pduformat) {
            if (CON_PDUFORMAT_FEEDBACK_STOP_CHARG == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_STOP_CHARG].pduformat) {
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_STOP_CHARG]), 0x00, sizeof(con_frame_info_t));
                memset(&(con_frame_info[CON_PDUFORMAT_STOP_CHARG]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_STOP_CHARG].time > con_frame_info[CON_PDUFORMAT_STOP_CHARG].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_STOP_CHARG]), 0x00, sizeof(con_frame_info_t));
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_STOP_CHARG].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_STOP_CHARG, &con_stop_charg[con_frame_info[CON_PDUFORMAT_STOP_CHARG].gunno - CONGUNNOA]);
                        con_frame_info[CON_PDUFORMAT_STOP_CHARG].count += 1;
                        printf("[CONTROLLER]-> stop charging [%s] \n", CONGUNNOA == con_stop_charg[con_frame_info[CON_PDUFORMAT_STOP_CHARG].gunno - CONGUNNOA].gnu_no ? "No.a" : "No.b");
                    }
                }
            }
        }

        if (CON_PDUFORMAT_STARTUP_FORCE == con_frame_info[CON_PDUFORMAT_STARTUP_FORCE].pduformat) {
            if (CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE].pduformat) {
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_STARTUP_FORCE]), 0x00, sizeof(con_frame_info_t));
                memset(&(con_frame_info[CON_PDUFORMAT_STARTUP_FORCE]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_STARTUP_FORCE].time > con_frame_info[CON_PDUFORMAT_STARTUP_FORCE].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_STARTUP_FORCE]), 0x00, sizeof(con_frame_info_t));
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_STARTUP_FORCE].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_STARTUP_FORCE, &con_startup_force[con_frame_info[CON_PDUFORMAT_STARTUP_FORCE].gunno - CONGUNNOA]);
                        con_frame_info[CON_PDUFORMAT_STARTUP_FORCE].count += 1;
                    }
                }
            }
        }

        if (CON_PDUFORMAT_LOCK_CTRL == con_frame_info[CON_PDUFORMAT_LOCK_CTRL].pduformat) {
            if (CON_PDUFORMAT_FEED_BACK_LOCK_CTRL == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL].pduformat) {
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL]), 0x00, sizeof(con_frame_info_t));
                memset(&(con_frame_info[CON_PDUFORMAT_LOCK_CTRL]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_LOCK_CTRL].time > con_frame_info[CON_PDUFORMAT_LOCK_CTRL].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_LOCK_CTRL]), 0x00, sizeof(con_frame_info_t));
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_LOCK_CTRL].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_LOCK_CTRL, &con_lock_ctrl[con_frame_info[CON_PDUFORMAT_LOCK_CTRL].gunno - CONGUNNOA]);
                        con_frame_info[CON_PDUFORMAT_LOCK_CTRL].count += 1;
                    }
                }
            }
        } else {
            memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEED_BACK_LOCK_CTRL]), 0x00, sizeof(con_frame_info_t));
        }

        if (CON_PDUFORMAT_POWER_CTRL == con_frame_info[CON_PDUFORMAT_POWER_CTRL].pduformat) {
            if (CON_PDUFORMAT_FEEDBACK_POWER_CTRL == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL].pduformat) {
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_POWER_CTRL]), 0x00, sizeof(con_frame_info_t));
                memset(&(con_frame_info[CON_PDUFORMAT_POWER_CTRL]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_POWER_CTRL].time > con_frame_info[CON_PDUFORMAT_POWER_CTRL].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_POWER_CTRL]), 0x00, sizeof(con_frame_info_t));
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_POWER_CTRL].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_POWER_CTRL, &con_power_ctrl[con_frame_info[CON_PDUFORMAT_POWER_CTRL].gunno - CONGUNNOA]);
                        con_frame_info[CON_PDUFORMAT_POWER_CTRL].count += 1;
                    }
                }
            }
        }

        if (CON_PDUFORMAT_SYS_GET_SET == con_frame_info[CON_PDUFORMAT_SYS_GET_SET].pduformat) {
            if (CON_PDUFORMAT_FEEDBACK_SYS_GET_SET == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET].pduformat) {
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_GET_SET]), 0x00, sizeof(con_frame_info_t));
                memset(&(con_frame_info[CON_PDUFORMAT_SYS_GET_SET]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_SYS_GET_SET].time > con_frame_info[CON_PDUFORMAT_SYS_GET_SET].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_SYS_GET_SET]), 0x00, sizeof(con_frame_info_t));
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_SYS_GET_SET].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_SYS_GET_SET, &con_sys_get_set[con_frame_info[CON_PDUFORMAT_SYS_GET_SET].gunno - CONGUNNOA]);
                        con_frame_info[CON_PDUFORMAT_SYS_GET_SET].count += 1;
                    }
                }
            }
        }

        if (CON_PDUFORMAT_CARINFO == con_frame_info[CON_PDUFORMAT_CARINFO].pduformat) {
            if (CON_PDUFORMAT_FEEDBACK_CARINFO == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_CARINFO].pduformat) {
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_CARINFO]), 0x00, sizeof(con_frame_info_t));
                memset(&(con_frame_info[CON_PDUFORMAT_CARINFO]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_CARINFO].time > con_frame_info[CON_PDUFORMAT_CARINFO].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_CARINFO]), 0x00, sizeof(con_frame_info_t));
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_CARINFO].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_CARINFO, &con_carinfo[con_frame_info[CON_PDUFORMAT_CARINFO].gunno - CONGUNNOA]);
                        con_frame_info[CON_PDUFORMAT_CARINFO].count += 1;
                    }
                }
            }
        }

        if (CON_PDUFORMAT_SYS_CHECK == con_frame_info[CON_PDUFORMAT_SYS_CHECK].pduformat) {
            if (CON_PDUFORMAT_FEEDBACK_SYS_CHECK == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_CHECK].pduformat) {
                memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_SYS_CHECK]), 0x00, sizeof(con_frame_info_t));
                memset(&(con_frame_info[CON_PDUFORMAT_SYS_CHECK]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_SYS_CHECK].time > con_frame_info[CON_PDUFORMAT_SYS_CHECK].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_SYS_CHECK]), 0x00, sizeof(con_frame_info_t));
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_SYS_CHECK].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_SYS_CHECK, &con_system_check);
                        con_frame_info[CON_PDUFORMAT_SYS_CHECK].count += 1;
                    }
                }
            }
        }

        if (CON_PDUFORMAT_TCU_ERROR == con_frame_info[CON_PDUFORMAT_TCU_ERROR].pduformat) {
            memset(&(con_frame_info[CON_PDUFORMAT_TCU_ERROR]), 0x00, sizeof(con_frame_info_t));
            con_send_data(CON_PDUFORMAT_TCU_ERROR, &con_tcu_error);
        }

        if (CON_PDUFORMAT_START_UPDATE == con_frame_info[CON_PDUFORMAT_START_UPDATE].pduformat) {
            if (CON_PDUFORMAT_FEEDBACK_START_UPDATE == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE].pduformat) {
                memset(&(con_frame_info[CON_PDUFORMAT_START_UPDATE]), 0x00, sizeof(con_frame_info_t));
            } else {
                if (controller_time() - con_frame_info[CON_PDUFORMAT_START_UPDATE].time > con_frame_info[CON_PDUFORMAT_START_UPDATE].timeout) {
                    memset(&(con_frame_info[CON_PDUFORMAT_START_UPDATE]), 0x00, sizeof(con_frame_info_t));

                    BaseUpdate::set_state(BaseUpdate::kFailed);
                } else {
                    if (++cycle >= con_frame_info[CON_PDUFORMAT_START_UPDATE].cycle / m_cycle) {
                        cycle = 0;
                        con_send_data(CON_PDUFORMAT_START_UPDATE, &con_start_update);
                        con_frame_info[CON_PDUFORMAT_START_UPDATE].count += 1;

                        printf("[CONTROLLER]-> start update data \n");
                    }
                }
            }
        }

        if (CON_PDUFORMAT_UPDATE_DATA == con_frame_info[CON_PDUFORMAT_UPDATE_DATA].pduformat) {
            memset(&(con_frame_info[CON_PDUFORMAT_UPDATE_DATA]), 0x00, sizeof(con_frame_info_t));
            con_send_data(CON_PDUFORMAT_UPDATE_DATA, &con_update_data);
        }

        if (CON_PDUFORMAT_FEEDBACK_START_UPDATE == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE].pduformat) {
            memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE]), 0x00, sizeof(con_frame_info_t));

            switch (ControllerParserMain::con_feedback_start_update.result) {
            case 0x01: //允许升级
                con_update_data.id = ota_send_id_++;
                for (int i = 0; (ota_send_size_ < ota_length_) && (i < 6); i++, ota_send_size_++) {
                    con_update_data.data[i] = ota_data_.at(ota_send_size_);
                    struct_flag = true;
                }
                if (struct_flag) {
                    struct_flag = false;

                    con_frame_info[CON_PDUFORMAT_UPDATE_DATA].pduformat = CON_PDUFORMAT_UPDATE_DATA; //first frame

                    m_cycle = ota_cycle_; //set cycle

                    //set update progress
                    BaseUpdate::set_state(BaseUpdate::kUpdateing);
                    BaseUpdate::set_progress(ota_send_size_ * 100 / ota_length_);

                    printf("[CONTROLLER]-> start update first data \n");
                }
                break;
            case 0x02: //拒绝升级
                BaseUpdate::set_state(BaseUpdate::kFailed);
                m_cycle = 250; //set cycle
                break;
            default:
                break;
            }
        } else if (CON_PDUFORMAT_FEEDBACK_UPDATE_DATA == ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_UPDATE_DATA].pduformat) {
            memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_UPDATE_DATA]), 0x00, sizeof(con_frame_info_t));

            switch (ControllerParserMain::con_feedback_update_data.result) {
            case 0x01: //成功
                con_update_data.id = ota_send_id_++;
                for (int i = 0; (ota_send_size_ < ota_length_) && (i < 6); i++, ota_send_size_++) {
                    con_update_data.data[i] = ota_data_.at(ota_send_size_);
                    struct_flag = true;
                }
                if (struct_flag) {
                    struct_flag = false;

                    con_frame_info[CON_PDUFORMAT_UPDATE_DATA].pduformat = CON_PDUFORMAT_UPDATE_DATA;

                    m_cycle = ota_cycle_; //set cycle

                    //set update progress
                    BaseUpdate::set_state(BaseUpdate::kUpdateing);
                    BaseUpdate::set_progress(ota_send_size_ * 100.0 / ota_length_);

                    //printf("[CONTROLLER]-> continue update data... \n");
                }
                break;
            case 0x02: //失败
                BaseUpdate::set_state(BaseUpdate::kFailed);
                m_cycle = 250; //set cycle
                break;
            case 0x03: //重发
                con_frame_info[CON_PDUFORMAT_UPDATE_DATA].pduformat = CON_PDUFORMAT_UPDATE_DATA;
                break;
            default:
                break;
            }
        } else if (CON_PDUFORMAT_UPDATE_RESULT == ControllerParserMain::con_frame_info[CON_PDUFORMAT_UPDATE_RESULT].pduformat) {
            memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_UPDATE_RESULT]), 0x00, sizeof(con_frame_info_t));

            switch (ControllerParserMain::con_update_result.result) {
            case 0x01: //成功
                BaseUpdate::set_state(BaseUpdate::kSuccess);
                BaseUpdate::set_progress(100.0);
                m_cycle = 250; //set cycle
                break;
            case 0x02: //失败
                BaseUpdate::set_state(BaseUpdate::kFailed);
                m_cycle = 250; //set cycle
                switch (ControllerParserMain::con_update_result.reupdate) {
                case 0x01: //重新升级
                    break;
                case 0x02: //不在重新升级
                    break;
                default:
                    break;
                }
                break;
            default:
                break;
            }
        } else {
            //...
        }

        msleep(m_cycle);
    }
}

quint16 ControllerSendMain::CheckCRC()
{
    return 0;
}

void ControllerSendMain::StartUpdate(qint32 subversion, qint32 revision, qint32 packLength, qint32 checkSum, QString updateType)
{
#if defined(CONTROLLERMAIN_DEBUG)
    qDebug() << "[CONTROLLER]-> ready update";
#endif

    BaseUpdate::set_state(BaseUpdate::kUpdateing);
    BaseUpdate::set_progress(0);

    QFile file;

    if ("ccu" == updateType) {
        file.setFileName(("./ota/ccu"));
    } else if ("awcu" == updateType) {
        file.setFileName(("./ota/awcu"));
    } else if ("bwcu" == updateType) {
        file.setFileName(("./ota/bwcu"));
    }

    if (!file.open(QIODevice::ReadOnly)) {
        BaseUpdate::set_state(BaseUpdate::kFailed);
        return;
    }

    ota_data_ = file.readAll();
    if (ota_data_.size() != packLength) {
        BaseUpdate::set_state(BaseUpdate::kFailed);
        return;
    }
    ota_length_ = packLength;

    /*
    if (checkCRC() != checkSum) {
        BaseUpdate::set_state(BaseUpdate::kFailed);
        return;
    } */

#if defined(CONTROLLERMAIN_DEBUG)
    qDebug() << "[CONTROLLER]-> start update ( fsize:" << ota_length_ << ")";
#endif

    ota_send_id_ = 0;
    ota_send_size_ = 0;

    con_start_update.length = packLength;
    con_start_update.crc = checkSum;
    con_start_update.version = ((subversion & 0x0F) << 4) + (revision & 0x0F);
    if ("ccu" == updateType) {
        con_start_update.type = 0x01;
    } else if ("awcu" == updateType) {
        con_start_update.type = 0x02;
    } else if ("bwcu" == updateType) {
        con_start_update.type = 0x03;
    } else {
        con_start_update.type = 0xFF;
    }

    memset(&(ControllerParserMain::con_frame_info[CON_PDUFORMAT_FEEDBACK_START_UPDATE]), 0x00, sizeof(con_frame_info_t));
    con_frame_info[CON_PDUFORMAT_START_UPDATE].cycle = 250;
    con_frame_info[CON_PDUFORMAT_START_UPDATE].count = 0;
    con_frame_info[CON_PDUFORMAT_START_UPDATE].timeout = 5000;
    con_frame_info[CON_PDUFORMAT_START_UPDATE].time = controller_time();
    con_frame_info[CON_PDUFORMAT_START_UPDATE].pduformat = CON_PDUFORMAT_START_UPDATE;
}
